home *** CD-ROM | disk | FTP | other *** search
- /* File: Play.c
- * Purpose: demonstrate Apple CD SC control
- * Date: 17 June 1988
- * Comments:
- * This code is written for LightSpeed C version 2.15
- * Create a project with this source plus MacTraps.
- * Requires some associated resources (in the file Play.r).
- * With this program on your hard disk, you can click
- * on a track on an Audio CD and the CD SC drive will
- * start audio play, beginning at that track and continuing
- * to the end of the disc.
- *
- * Revisions:
- *
- * Converted to converted to mpw 3.0 8/29 mb
- *
- * Build instructions:
- *
- * rez -c MBAU :RIncludes:Types.r Play.r -o Play
- * c Play.c -w
- * link Play.c.o -o Play -c aucd ∂
- * "{CLibraries}"CRuntime.o ∂
- * "{CLibraries}"CInterface.o ∂
- * "{Libraries}"Interface.o
- *
- *
- */
-
- #include <types.h> /* Nearly always required */
- #include <quickdraw.h> /* To access the qd globals */
- #include <fonts.h> /* Only for InitFonts() trap */
- #include <events.h> /* GetNextEvent(), ... */
- #include <windows.h> /* GetNewWindow(), ... */
- #include <dialogs.h> /* InitDialogs() and GetNewDialog() */
- #include <menus.h> /* EnableItem(), DisableItem() */
- #include <desk.h> /* SystemTask(), SystemClick() */
- #include <TextEdit.h>
- #include <Resources.h> /* GetResource() */
- #include <OSUtils.h> /* SysBeep() */
- #include <ToolUtils.h>
- #include <SegLoad.h>
- #include <Strings.h>
- #include <Devices.h>
- #include <Files.h>
- #include <Packages.h>
-
- #include <Memory.h>
- #include <OSEvents.h>
-
- /* Some constants, from the CD SC Developer's Guide chapter 7 */
- #define TRACKADDR 2
- #define STEREO 9
- #define INPROGRESS 0
-
- /* Some commands, from the CD SC Developer's Guide chapter 7 */
- #define APLAY 104
- #define ASTOP 106
- #define ASTATUS 107
-
- /* The resource ID I use for my error dialog */
- #define errorID 128
-
- /* prototype function declarations. */
- void Error(char *, short);
- void ExtractTrackNo(char *, short *);
- OSErr AStop(short, short);
- OSErr APlay(short, short);
- OSErr Play(char *, short);
- short GetDrvRefNum(short);
- void PlayOnStartup(short);
- Boolean AskAndPlay(void);
- void main(void);
- pascal void Debugger(/*void*/) extern 0xA9FF;
-
- /************************************************************************
- *
- * Function: Error
- *
- * Purpose: Report an error to the user.
- *
- * Returns: nothing
- *
- * Side Effects: none.
- *
- * Description: Takes a string and a result code. Convert the result
- * into a pascal string using NumToString() and then just
- * do a switch to determine which friendly error message
- * to put up on the screen. ParamText() sets up the alert
- * so that it has the correct information. Use Alert() to
- * actually display the message to the user.
- *
- ************************************************************************/
- void
- Error(where, result)
- char *where;
- short result;
- {
- DialogPtr dPtr;
- short itemhit;
- Str255 strResult;
- long longResult;
-
- longResult = result;
- NumToString(longResult, strResult);
-
- switch (result)
- {
- case -56:
- ParamText(where, strResult, "\pSpecified drive number doesn't match any number in the drive queue.", "\p");
- break;
- case -51:
- ParamText(where, strResult, "\pReference number specifies nonexistent access path.", "\p");
- break;
- case -50:
- ParamText(where, strResult, "\pError in parameter list.", "\p");
- break;
- case -43:
- ParamText(where, strResult, "\pFile not found.", "\p");
- break;
- case -36:
- ParamText(where, strResult, "\pI/O error.", "\p");
- break;
- case -35:
- ParamText(where, strResult, "\pNo such volume.", "\p");
- break;
- case -21:
- ParamText(where, strResult, "\pBad unit number.", "\p");
- break;
- default:
- ParamText(where, strResult, "\p", "\p");
- break;
- }
-
- Alert(errorID, (ProcPtr) NULL);
- }
-
-
- /************************************************************************
- *
- * Function: ExtractTrackNo
- *
- * Purpose: Extract track number in BCD from PString
- *
- * Returns: nothing
- *
- * Side Effects: *track gets a new value
- *
- * Description: Extract track number in BCD from PString "name".
- * "name" is always of the form "Track XX", where XX
- * ranges from " 1" (1 with a leading space) to "99"
- * (You can't have more than 99 tracks on a compact disc.
- * Bet you didn't know that, did you? Right in the "Yellow
- * Book" specification of compact disc encoding.)
- *
- ************************************************************************/
- void
- ExtractTrackNo(name, track)
- char *name;
- short *track;
- {
- short size;
- short t;
-
- t = 0;
- size = *name;
- if (name[size-1] != ' ')
- t = (name[size-1] - '0') * 16;
- t += name[size] - '0';
-
- *track = t;
- }
-
- /************************************************************************
- *
- * Function: AStop
- *
- * Purpose: stop playing an audio track
- *
- * Returns: OSErr. Probably either
- * noErr everything's hunky-dory!
- * paramErr you messed up the call somehow.
- *
- * Side Effects: stops play.
- *
- * Description: The track that you pass in is the LAST track that you
- * want to have play. This means that if you wanted to
- * play only one track, you'd pass the same value to
- * this routine and APlay() [q.v.]
- *
- * Note that this routine isn't called in this sample,
- * but it's included for your enjoyment.
- *
- ************************************************************************/
- OSErr
- AStop(track, refNum)
- short track;
- short refNum;
- {
- struct {
- short addrFormat;
- long address;
- } csParam;
-
- csParam.addrFormat = TRACKADDR;
- csParam.address = track;
- return (Control(refNum, ASTOP, &csParam));
- }
-
- /************************************************************************
- *
- * Function: APlay
- *
- * Purpose: start playing an audio track
- *
- * Returns: OSErr. Probably either
- * noErr everything's hunky-dory!
- * paramErr you messed up the call somehow.
- *
- * Side Effects: starts play. By default, this will play until the
- * end of the disc.
- *
- * Description: The track that you pass in is the first track that you
- * want to have play.
- *
- ************************************************************************/
- OSErr
- APlay(track, refNum)
- short track;
- short refNum;
- {
- struct {
- short addrFormat;
- long address;
- short stopAddress;
- short playMode;
- } csParam;
-
- csParam.addrFormat = TRACKADDR;
- csParam.address = track; /* must be in BCD */
- csParam.stopAddress = 0;
- csParam.playMode = STEREO;
- return (Control(refNum, APLAY, &csParam));
- }
-
-
- /************************************************************************
- *
- * Function: Play
- *
- * Purpose: play a track, given it's "filename"
- *
- * Returns: OSErr
- * whatever is returned by APlay()
- *
- * Side Effects: starts play of the audio track.
- *
- * Description: The two parameters passed in are the file name (which
- * will always be of the form "Track XX", XX varying from
- * " 1" to "99") and the driver reference number. Extract
- * the track number and use it to call APlay() [q.v.]
- *
- ************************************************************************/
- OSErr
- Play(name, driveNumber)
- char *name;
- short driveNumber;
- {
- short trackno;
- OSErr result;
-
- ExtractTrackNo(name, &trackno);
- return( APlay(trackno, driveNumber) );
- }
-
-
- /************************************************************************
- *
- * Function: GetDrvRefNum
- *
- * Purpose: Get the driver reference number
- *
- * Returns: short. The driver reference number
- *
- * Side Effects: none.
- *
- * Description: PBHGetVInfo() will retrieve the driver reference
- * number, given the vRefNum associated with a file.
- * We acquired the vRefNum as something passed into
- * the program, either by SFGetFile() or by
- * GetAppFile().
- *
- * We'll use the driver reference number in all our
- * control calls to the driver.
- *
- ************************************************************************/
- short
- GetDrvRefNum(vRefNum)
- short vRefNum;
- {
- HParamBlockRec io;
-
- io.volumeParam.ioCompletion = NULL;
- io.volumeParam.ioNamePtr = NULL;
- io.volumeParam.ioVRefNum = vRefNum;
- io.volumeParam.ioVolIndex = 0;
- PBHGetVInfo(&io, false);
- return io.volumeParam.ioVDRefNum;
- }
-
-
-
- /************************************************************************
- *
- * Function: PlayOnStartup
- *
- * Purpose: Play the files passed in to our application
- *
- * Returns: nothing
- *
- * Side Effects: plays some files.
- *
- * Description: Loop, using GetAppFiles() to get the next "file"
- * (actually audio CD track) to play. Continue until
- * we run out of files to play or until we get some
- * error while trying to play a track.
- *
- * Exercise to the programmer:
- * As this routine is currently written, it doesn't
- * handle opening multiple tracks at once. (e.g. the
- * user selects five tracks and opens them all.) Right
- * now, you'll only hear the last track (each Play()
- * command cancels the previous one.)
- *
- * Add a routine to check the status of the CD SC
- * drive (using AStatus) so that you wait for a track
- * to finish before starting the next track.
- *
- ************************************************************************/
- void
- PlayOnStartup(count)
- short count;
- {
- short i;
- AppFile app;
- OSErr result;
-
- for (i = 0; i++<count; )
- {
- GetAppFiles(i, &app);
- if (app.fType == 'trak')
- {
- result = Play((char *)app.fName, GetDrvRefNum(app.vRefNum));
- if (result != noErr)
- Error("\pPlay returned", result);
- }
- }
- }
-
-
- /************************************************************************
- *
- * Function: AskAndPlay
- *
- * Purpose: Prompt the user for a track and play it
- *
- * Returns: Boolean. Either:
- * true the user wants us to continue
- * false the user wants us to exit, or an error
- * occurred.
- *
- * Side Effects: may play a track.
- *
- * Description: Use SFGetFile() with a specific type ('trak') to get
- * a list of just audio CD tracks. If the user selects
- * an audio CD track, play it.
- *
- ************************************************************************/
- Boolean
- AskAndPlay()
- {
- SFReply sf;
- short refnum;
- static Point where = {100,100};
- static OSType sftl = 'trak';
- Boolean result;
- OSErr errorCode;
-
- result = true;
- FlushEvents(everyEvent-diskMask,0);
- SFGetFile(where, "\pSelect Track to Play", (ProcPtr)NULL,
- 1, &sftl, (ProcPtr)NULL, &sf);
- if (!sf.good)
- result = false;
- else
- {
- errorCode = Play((char *)sf.fName, GetDrvRefNum(sf.vRefNum));
- if (errorCode != noErr)
- {
- Error("\pPlay returned", result);
- result = false;
- }
- }
- return result;
- }
-
-
- /************************************************************************
- *
- * Function: main
- *
- * Purpose: The Master Cylinder. This is where we start.
- *
- * Returns: nothing.
- *
- * Side Effects: does whatever you tell it.
- *
- * Description: Do the standard Macintosh initialization. Following
- * all the boilerplate, use CountAppFiles() to see how
- * we were started. We could be started one of three
- * ways:
- * 1) The user opened our application. We will have
- * a count of zero. Go ask the user for a track.
- * 2) The user opened an audio CD track "file". We
- * will have a non-zero count. Go play the track(s)
- * that the user asked.
- *
- ************************************************************************/
- void
- main()
- {
- short message, count;
- short refNum;
-
- MaxApplZone();
- MoreMasters();
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0);
-
- InitCursor();
- FlushEvents(everyEvent-diskMask,0);
-
- CountAppFiles(&message, &count);
- if (count)
- PlayOnStartup(count);
- else
- while (AskAndPlay())
- ; /* null loop */
- }
-